/**
 @file ctc_asw_learning_aging.c

 @date 2020-06-15

 @version v1.0


*/

/****************************************************************************
*
* Header Files
*
****************************************************************************/
#include "ctc_asw_common.h"
#include "ctc_learning_aging.h"
#include "ctc_asw_learning_aging.h"
#include "ctc_asw_interrupt.h"
#include "asw/include/drv_api.h"

/****************************************************************************
*
* Function
*
*****************************************************************************/
int32
ctc_asw_station_move_sync_data (uint8 lchip, uint32 intr, void* p_data)
{
    int32   ret = 0;
    uint32  cmd = 0;
    uint32  move_fifo_empty = 0;
    uint8   entry_idx = 0;
    hw_mac_addr_t  hw_mac = {0};
    MoveFifoReg_m     move_fifo_reg;
    SendtoFifoState_m sendto_fifo_state;
    static ctc_learning_cache_t ctc_station[CTC_MAX_LOCAL_CHIP_NUM];
    CTC_INTERRUPT_EVENT_FUNC cb = NULL;
    CTC_ERROR_RETURN(_ctc_asw_intr_get_event_func(lchip, CTC_EVENT_L2_SW_LEARNING, &cb))
    cmd = DRV_IOR(SendtoFifoState_t,DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip,0,cmd,&sendto_fifo_state));
    move_fifo_empty = GetSendtoFifoState(V,moveFifoEmpty_f,&sendto_fifo_state);
    while (move_fifo_empty == 0 && entry_idx < CTC_LEARNING_CACHE_MAX_INDEX)
    {
        cmd = DRV_IOR(MoveFifoReg_t,DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip,0,cmd,&move_fifo_reg));
        GetMoveFifoReg(A,macAddr_f,&move_fifo_reg,hw_mac);
        CTC_ASW_SET_USER_MAC(ctc_station[lchip].learning_entry[entry_idx].mac,hw_mac );
        ctc_station[lchip].learning_entry[entry_idx].global_src_port = GetMoveFifoReg(V,sourcePortid_f,&move_fifo_reg);
        ctc_station[lchip].learning_entry[entry_idx].fid = GetMoveFifoReg(V,fid_f,&move_fifo_reg);
        CTC_SET_FLAG(ctc_station[lchip].learning_entry[entry_idx].flag,CTC_L2_LEARN_CACHE_STATION_MOVE);
        if (GetMoveFifoReg(V,isSaOverlimit_f,&move_fifo_reg))
        {
            CTC_SET_FLAG(ctc_station[lchip].learning_entry[entry_idx].flag,CTC_L2_LEARN_CACHE_OVER_MAC_LIMIT);
        }
        entry_idx++;
        cmd = DRV_IOR(SendtoFifoState_t,DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip,0,cmd,&sendto_fifo_state));
        move_fifo_empty = GetSendtoFifoState(V,moveFifoEmpty_f,&sendto_fifo_state);
    }
    ctc_station[lchip].entry_num = entry_idx;
    if(cb && ctc_station[lchip].entry_num)
    {
        cb(lchip, &ctc_station[lchip]);
        ctc_station[lchip].entry_num = 0;
    }
    return ret;
}

int32
ctc_asw_learning_aging_sync_data(uint8 lchip, uint32 intr, void* p_data)
{
    int32   ret = 0;
    uint32  cmd = 0;
    uint32  learn_fifo_empty = 0;
    uint8   entry_idx = 0;
    hw_mac_addr_t  hw_mac = {0};
    SendtoFifoState_m sendto_fifo_state;
    LearnFifoReg_m    learn_fifo_reg;
    static ctc_learning_cache_t ctc_learning[CTC_MAX_LOCAL_CHIP_NUM];
    CTC_INTERRUPT_EVENT_FUNC cb = NULL;

    CTC_ERROR_RETURN(_ctc_asw_intr_get_event_func(lchip, CTC_EVENT_L2_SW_LEARNING, &cb))
    cmd = DRV_IOR(SendtoFifoState_t,DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip,0,cmd,&sendto_fifo_state));
    learn_fifo_empty = GetSendtoFifoState(V,learnFifoEmpty_f,&sendto_fifo_state);

    while (learn_fifo_empty == 0 && entry_idx < CTC_LEARNING_CACHE_MAX_INDEX)
    {
        cmd = DRV_IOR(LearnFifoReg_t,DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip,0,cmd,&learn_fifo_reg));
        GetLearnFifoReg(A,macAddr_f,&learn_fifo_reg,hw_mac);
        CTC_ASW_SET_USER_MAC(ctc_learning[lchip].learning_entry[entry_idx].mac,hw_mac );
        ctc_learning[lchip].learning_entry[entry_idx].global_src_port = GetLearnFifoReg(V,portId_f,&learn_fifo_reg);
        ctc_learning[lchip].learning_entry[entry_idx].fid = GetLearnFifoReg(V,fid_f,&learn_fifo_reg);
        if (GetLearnFifoReg(V,isSaOverlimit_f,&learn_fifo_reg))
        {
            CTC_SET_FLAG(ctc_learning[lchip].learning_entry[entry_idx].flag,CTC_L2_LEARN_CACHE_OVER_MAC_LIMIT);
        }
        else
        {
            ctc_learning[lchip].learning_entry[entry_idx].flag = 0;
        }
        entry_idx++;
        cmd = DRV_IOR(SendtoFifoState_t,DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip,0,cmd,&sendto_fifo_state));
        learn_fifo_empty = GetSendtoFifoState(V,learnFifoEmpty_f,&sendto_fifo_state);
    }
    ctc_learning[lchip].entry_num = entry_idx;
    if(cb && ctc_learning[lchip].entry_num)
    {
        cb(lchip, &ctc_learning[lchip]);
        ctc_learning[lchip].entry_num = 0;
    }

    return ret;
}

#define ______API______
int32
ctc_asw_aging_set_property(uint8 lchip, ctc_aging_table_type_t  tbl_type, ctc_aging_prop_t aging_prop, uint32 value)
{
    uint32    cmd = 0;
    int32     ret = 0;
    AgeTimerCtrl_m age_timer_ctrl;

    if (CTC_AGING_TBL_MAC !=  tbl_type)
    {
        return CTC_E_INVALID_PARAM;
    }
    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(AgeTimerCtrl_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, 0, cmd, &age_timer_ctrl);
    switch (aging_prop)
    {
    	case CTC_AGING_PROP_INTERVAL:
        	SetAgeTimerCtrl(V, agingRTrip_f, &age_timer_ctrl, value);
        	break;
    	case CTC_AGING_PROP_AGING_SCAN_EN:
        	value = !!value;
        	SetAgeTimerCtrl(V, agingEn_f, &age_timer_ctrl, value);
        	break;
   	 default :
        	ret = CTC_E_INVALID_PARAM;
        	break;
    }
    cmd = DRV_IOW(AgeTimerCtrl_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, 0, cmd, &age_timer_ctrl);
    CTC_API_UNLOCK(lchip);
    return ret;
}

int32
ctc_asw_aging_get_property(uint8 lchip, ctc_aging_table_type_t  tbl_type, ctc_aging_prop_t aging_prop, uint32* value)
{
    uint32 cmd = 0;
    int32  ret = 0;
    AgeTimerCtrl_m age_timer_ctrl;
    uint32 temp_val;
    if (CTC_AGING_TBL_MAC !=  tbl_type)
    {
        return CTC_E_INVALID_PARAM;
    }
    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(AgeTimerCtrl_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, 0, cmd, &age_timer_ctrl);
    switch (aging_prop)
    {
        case CTC_AGING_PROP_INTERVAL:
            *value = GetAgeTimerCtrl(V, agingRTrip_f, &age_timer_ctrl);
            break;
        case CTC_AGING_PROP_AGING_SCAN_EN:
            temp_val = GetAgeTimerCtrl(V, agingEn_f, &age_timer_ctrl);
            *value = temp_val;
            break;
        default:
            ret = CTC_E_INVALID_PARAM;
            break;
    }
    CTC_API_UNLOCK(lchip);
    return ret;
}

int32
ctc_asw_learning_aging_init(uint8 lchip, void* global_cfg)
{
    /* callback func for maclimit or station move */
    CTC_ERROR_RETURN(_ctc_asw_intr_register_cb_func(lchip, CTC_ASW_CB_L2_STATION_MOVE,
        ctc_asw_station_move_sync_data));
    /* callback func for software learning */
    CTC_ERROR_RETURN(_ctc_asw_intr_register_cb_func(lchip, CTC_ASW_CB_L2_SW_LEARNING,
        ctc_asw_learning_aging_sync_data));
    return CTC_E_NONE;
}

int32
ctc_asw_learning_aging_deinit(uint8 lchip)
{
    return CTC_E_NONE;
}
